package cn.yunyichina.utils.convert;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.util.*;

/**
 * Created by Lullaby on 2016/10/20.
 */
public class XmlUtils {

    /**
     * 判断是否是xml(这写法可以说很强势了...)
     *
     * @param data
     * @return
     */
    public static boolean isXml(String data) {
        try {
            DocumentHelper.parseText(data);
        } catch (DocumentException e) {
            return false;
        }

        return true;
    }

    /**
     * map转xml(仅限单层xml)
     *
     * @param map
     * @return
     */
    public static String mapToXml(Map<String, String> map) {
        Element xml = DocumentHelper.createElement("xml");

        for (Map.Entry<String, String> entry : map.entrySet()) {
            xml.addElement(entry.getKey()).addCDATA(entry.getValue());
        }

        return xml.asXML();
    }

    /**
     * xml转map(仅限单层map)
     *
     * @param xml
     * @return
     * @throws DocumentException
     */
    public static Map<String, String> xmlToMap(String xml) {
        Map<String, String> result = new HashMap<>();

        Document doc;
        try {
            doc = DocumentHelper.parseText(xml);
        } catch (DocumentException e) {
            throw new RuntimeException("Parse xml throws exception.", e);
        }

        Element root = doc.getRootElement();
        for (Iterator<Element> iterator = root.elementIterator(); iterator.hasNext(); ) {
            Element e = iterator.next();
            result.put(e.getName(), e.getText());
        }

        return result;
    }

    /**
     * 递归遍历xml转map
     *
     * @param xml
     * @return
     * @throws DocumentException
     */
    public static Map<String, Object> xmlToMapRecursively(String xml) throws DocumentException {
        Map<String, Object> map = new HashMap<>();
        Document doc = DocumentHelper.parseText(xml);
        Element root = doc.getRootElement();

        xmlToMapRecursively(root, map);

        return map;
    }

    /**
     * 递归遍历xml(有子节点则用list存储防重复元素)
     *
     * @param root
     * @param map
     */
    private static void xmlToMapRecursively(Element root, Map<String, Object> map) {
        List elements = root.elements();

        if (elements.size() == 0) {
            map.put(root.getName(), root.getData());
        } else {
            List<Object> tempList = new ArrayList<>();
            for (Object object : elements) {
                Map<String, Object> tempMap = new HashMap<>();
                Element element = (Element) object;

                xmlToMapRecursively(element, tempMap);

                tempList.add(tempMap);
                map.put(root.getName(), tempList);
            }
        }
    }

    /**
     * 统一使用map存储xml节点(重复元素将被覆盖)
     *
     * @param xml
     * @return
     * @throws DocumentException
     */
    public static Map<String, Object> xmlToUnifiedMap(String xml) throws DocumentException {
        Map<String, Object> map = new HashMap<>();
        Document doc = DocumentHelper.parseText(xml);
        Element root = doc.getRootElement();

        xmlToUnifiedMap(root, map);

        return map;
    }

    /**
     * 递归遍历xml(统一使用map存储，重复元素将被覆盖)
     *
     * @param root
     * @param map
     */
    private static void xmlToUnifiedMap(Element root, Map<String, Object> map) {
        List elements = root.elements();

        if (elements.size() == 0) {
            map.put(root.getName(), root.getData());
        } else {
            for (Object object : elements) {
                Map<String, Object> tempMap = new HashMap<>();
                Element element = (Element) object;

                xmlToUnifiedMap(element, tempMap);

                map.putAll(tempMap);
            }
        }
    }

    /**
     * xml转map(支持两层xml节点)
     *
     * @param xml
     * @return
     */
    public static Map<String, String> xmlToMapWithSecondRoot(String xml) {
        Map<String, String> result = new HashMap<>();

        Document doc;
        try {
            doc = DocumentHelper.parseText(xml);
        } catch (DocumentException e) {
            e.printStackTrace();
            throw new RuntimeException("Parse xml throws exception.");
        }

        Element root = doc.getRootElement();

        for (Iterator<Element> iterator = root.nodeIterator(); iterator.hasNext(); ) {
            Element element = iterator.next();
            for (Iterator<Element> ite = element.nodeIterator(); ite.hasNext(); ) {
                Element ele = ite.next();
                result.put(ele.getName(), ele.getText());
            }
        }

        return result;
    }

}
